package com.itheima.service.db.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.domain.db.AnalysisByDay;
import com.itheima.domain.db.DataCount;
import com.itheima.domain.db.EachDataCount;
import com.itheima.mapper.AnalysisByDayMapper;
import com.itheima.mapper.LogMapper;
import com.itheima.service.db.AnalysisByDayService;
import com.itheima.util.ComputeUtil;
import com.itheima.vo.AnalysisSummaryVo;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;

@Service
public class AnalysisByDayServiceImpl implements AnalysisByDayService {

    @Autowired
    private LogMapper logMapper;
    @Autowired
    private AnalysisByDayMapper analysisByDayMapper;

    //分析log,生成tb_analysis_by_day
    @Override
    public void analysis() {

        System.out.println("===================开始日志分析======================");
        String todayTime = DateUtil.offsetDay(new Date(), 0).toDateStr();
        String yesterdayTime = DateUtil.offsetDay(new Date(), -1).toDateStr();

        //准备AnalysisByDay对象
        Integer numRegistered = logMapper.countByTimeAndType(todayTime, "0102").intValue();//今日注册
        Integer numActive = logMapper.countByTime(todayTime).intValue();//今日活跃
        Integer numLogin = logMapper.countByTimeAndType(todayTime, "0101").intValue();//今日登陆
        Integer numRetentionId = logMapper.keep(yesterdayTime,todayTime).intValue();//次日留存


        //record_date 分析表记录行的日期
        //1. 先查询是否存在今天的统计数据
        QueryWrapper<AnalysisByDay> wrapper = new QueryWrapper<>();
        wrapper.eq("record_date",todayTime);
        AnalysisByDay analysisByDay = analysisByDayMapper.selectOne(wrapper);
        if(analysisByDay == null){
            //没有今天的数据 ===> 进行保存
            analysisByDay = new AnalysisByDay();

            analysisByDay.setRecordDate(new Date());
            analysisByDay.setNumRegistered(numRegistered);
            analysisByDay.setNumActive(numActive);
            analysisByDay.setNumLogin(numLogin);
            analysisByDay.setNumRetention1d(numRetentionId);

            //新增
            analysisByDayMapper.insert(analysisByDay);
        }else {

            //有今天的数据 ===> 进行修改
            analysisByDay.setNumRegistered(numRegistered);
            analysisByDay.setNumActive(numActive);
            analysisByDay.setNumLogin(numLogin);
            analysisByDay.setNumRetention1d(numRetentionId);

            //修改updated-修改日期
            analysisByDay.setUpdated(new Date());

            //修改
            analysisByDayMapper.updateById(analysisByDay);
        }
    }

    //查询首页概要统计信息
    @Override
    public AnalysisSummaryVo analysisSummary() {
        //准备基础数据
        String today = DateUtil.offsetDay(new Date(), 0).toDateStr();//今天
        String yesterday = DateUtil.offsetDay(new Date(),-1).toDateStr();//昨天
        String lastWeekDay = DateUtil.offsetDay(new Date(), -7).toDateStr();//过去七天
        String lastMonthDay = DateUtil.offsetDay(new Date(),-30).toDateStr();//过去30天
        //分别查询 昨日和今日的分析表数据(为后面涨跌率拿数据)
        //今日
        QueryWrapper<AnalysisByDay> wrapperToday = new QueryWrapper<>();
        wrapperToday.eq("record_date",today);
        AnalysisByDay todayData = analysisByDayMapper.selectOne(wrapperToday);
        //昨日
        QueryWrapper<AnalysisByDay> wrapperYesterday = new QueryWrapper<>();
        wrapperYesterday.eq("record_date",yesterday);
        AnalysisByDay yesterdayData = analysisByDayMapper.selectOne(wrapperYesterday);

        //查询九个数据
        //累计用户数
         Long cumulativeUsers = analysisByDayMapper.countRegisterNum();
         //过去30天活跃用户数
         Long activePassMonth = analysisByDayMapper.countActiveNum(lastMonthDay,today);
         //过去7天活跃用户数
         Long activePassWeek = analysisByDayMapper.countActiveNum(lastWeekDay,today);
         //今日新增(注册)用户数
         Long newUsersToday = todayData.getNumRegistered().longValue();
         //今日新增用户涨跌率
         BigDecimal newUsersTodayRate = ComputeUtil.computeRate(todayData.getNumRegistered(),yesterdayData.getNumRegistered());
         //今日登陆次数
         Long loginTimesToday = todayData.getNumLogin().longValue();
         //今日登陆次数涨跌率
         BigDecimal loginTimesTodayRate = ComputeUtil.computeRate(todayData.getNumLogin(),yesterdayData.getNumLogin());
         //今日活跃用户数量
         Long activeUsersToday = todayData.getNumActive().longValue();
         //
        BigDecimal activeUsersTodayRate = ComputeUtil.computeRate(todayData.getNumActive(),yesterdayData.getNumActive());


        //3. 组装AnalysisSummaryVo对象
        AnalysisSummaryVo analysisSummaryVo = new AnalysisSummaryVo();
        analysisSummaryVo.setCumulativeUsers(cumulativeUsers);

        analysisSummaryVo.setActivePassMonth(activePassMonth);
        analysisSummaryVo.setActivePassWeek(activePassWeek);

        analysisSummaryVo.setNewUsersToday(newUsersToday);
        analysisSummaryVo.setNewUsersTodayRate(newUsersTodayRate);
        analysisSummaryVo.setLoginTimesToday(loginTimesToday);
        analysisSummaryVo.setLoginTimesTodayRate(loginTimesTodayRate);
        analysisSummaryVo.setActiveUsersToday(activeUsersToday);
        analysisSummaryVo.setActiveUsersTodayRate(activeUsersTodayRate);

        return analysisSummaryVo;
    }


    //todo 数据统计
    @Override
    public DataCount DateGather(Long startDate, Long endDate, Integer type) {
        //1、处理起始日期；hutool工具
        Date thisYearEndDate =DateUtil.date(endDate);
        Date thisYearStartDate =DateUtil.date(startDate);
        //2、起止日期相差天数，要包含起止日期的全部时间，查询时需要+1
        Long days = DateUtil.between(thisYearEndDate, thisYearStartDate, DateUnit.DAY)+1;
        //3、组装统计信息对象
        DataCount dataCount = new DataCount();
        //EndDate的年、月、日
        int year = DateUtil.year(thisYearEndDate);
        int month = DateUtil.month(thisYearEndDate);
        int dayOfMonth = DateUtil.dayOfMonth(thisYearEndDate);
        //今天当天的年、月、日
        Date today = DateUtil.date();
        int yearToday = DateUtil.year(today);
        int monthToday = DateUtil.month(today);
        int dayOfMonthToday = DateUtil.dayOfMonth(today);

        //3-1:todo 处理本周和本月，特殊点：endDay必是当天
        if (year==yearToday&&month==monthToday&&dayOfMonth==dayOfMonthToday){
            if (days==8){
                //查询本周的数据 或刚好前7天唯一一种情况；
                Calendar cal = Calendar.getInstance();
                Integer dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天(周日是作为第一天)
                System.out.println("当前是本周的第几天："+dayWeek);

                //处理调用工具类的参数：
                thisYearStartDate =DateUtil.offsetDay(thisYearEndDate,-dayWeek+1);
                days=dayWeek.longValue();
            }else if (days==31){
                //查询的是本月 或者刚好前30天唯一一种情况；
                LocalDate todayLocalDate = LocalDate.now();
                //本月的第一天
                LocalDate firstday = LocalDate.of(todayLocalDate.getYear(), todayLocalDate.getMonth(), 1);//2021-07-01
                ZonedDateTime zonedDateTime = firstday.atStartOfDay(ZoneId.systemDefault());

                //处理调用工具类的参数：
                thisYearStartDate = Date.from(zonedDateTime.toInstant()); //本月的第一天Date
                days = DateUtil.between(thisYearEndDate, thisYearStartDate, DateUnit.DAY) + 1;
                System.out.println("本月第一天的日期：" + thisYearStartDate);
            }
        }

        //3-2:endDate不是今天，则必不是本周、本月
        /*调用工具类的方法：getDataCount(Integer type,Long days,Date startDate)
         * 参数一：查询类型 type
         * 参数二：起止日期涉及的天数  days
         * 参数三：查询的开始时间  thisYearStartDate
         * */
        //3-2:今年的数据
        ArrayList<EachDataCount> thisYearDateList = getDataCount(type, days, thisYearStartDate);
        dataCount.setThisYear(thisYearDateList);//今年数据
        //3-3:组装同期去年的日期
        year = DateUtil.year(thisYearEndDate)-1;
        String lastYearStartDateString=year+"-"+month+"-"+dayOfMonth;
        Date lastYearStartDate =DateUtil.parse(lastYearStartDateString);
        ArrayList<EachDataCount> lastYearDateList = getDataCount(type, days, lastYearStartDate);
        dataCount.setLastYear(lastYearDateList);//去年数据

        //返回对象
        return dataCount;
    }

    //工具类：数据统计的工具类，用来统计一段时间的操作人数，返回一个List
    private ArrayList<EachDataCount> getDataCount(Integer type,Long days,Date startDate){
        //1、存放数据的容器：
        ArrayList<EachDataCount> eachDataCountList = new ArrayList<>();
        //2、循环查询起止日期内每天的信息
        for (int i = 0; i <days ; i++) {
            //4、根据record_date查询，获取当天的日期，hutool工具，时间偏移
            String theDay = DateUtil.offsetDay(startDate, i).toDateStr();
            QueryWrapper<AnalysisByDay> wrapper = new QueryWrapper<>();
            wrapper.eq("record_date",theDay);
            AnalysisByDay analysisByDay = analysisByDayMapper.selectOne(wrapper);//查询`表tb_analysis_by_day`
            //5、根据type判断类型:101 新增 102 活跃用户 103 次日留存率确定返回值
            if (type==101){
                //统计新增用户:numRegistered
                Integer numRegistered = analysisByDay.getNumRegistered();
                EachDataCount eachDataCount = new EachDataCount();
                eachDataCount.setAmount(numRegistered);
                eachDataCount.setTitle(theDay);
                eachDataCountList.add(eachDataCount);
            }else if (type==102){
                //统计活跃用户 numActive
                Integer numActive = analysisByDay.getNumActive();
                EachDataCount eachDataCount = new EachDataCount();
                eachDataCount.setAmount(numActive);
                eachDataCount.setTitle(theDay);
                eachDataCountList.add(eachDataCount);
            }else {
                //统计次日留存率103 numRetention1d
                Integer numRetention1d = analysisByDay.getNumRetention1d();
                EachDataCount eachDataCount = new EachDataCount();
                eachDataCount.setAmount(numRetention1d);
                eachDataCount.setTitle(theDay);
                eachDataCountList.add(eachDataCount);
            }
        }
        return eachDataCountList;
    }



}
